import wx
import tkinter as tk
from tkinter import filedialog
from tkinter import ttk
import time
import os
from PIL import Image
import re
# import cv2
# import numpy as np


class CompressFrame(wx.Frame):

    photo_list = ()

    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, '批量图片压缩工具', size=(500, 600))
        self.Centre()
        panel = wx.Panel(self)

        self.label_expect_size = wx.StaticText(
            panel, label="1.预期压缩后的图片为多少KB：请输入罗马数字,\n常见单位转换：1MB=1024KB，2MB=2048KB", pos=(60, 60), size=(370, 40))
        self.text_expect_size = wx.TextCtrl(
            panel, style=wx.TE_LEFT, pos=(60, 105), size=(370, 30))
        self.label_expect_filePath = wx.StaticText(
            panel, label="2.预期存放的文件夹路径：如果未指定路径，默认会在第一张照片\n的路径中，创建新的文件夹CompressedPhotos。例：D:\Blog", pos=(60, 155), size=(370, 40))
        self.text_expect_filePath = wx.TextCtrl(
            panel, style=wx.TE_LEFT, pos=(60, 200), size=(370, 30))

        methods_list = ["JPG/JPEG", "PNG"]
        self.method_choose_rbox = wx.RadioBox(panel, label="3.请选择需要被压缩的图片的格式：", pos=(
            60, 240), choices=methods_list, majorDimension=1, style=wx.RA_SPECIFY_ROWS)

        self.label_select_photos = wx.StaticText(
            panel, label="4.请选择想压缩的图片：一次只能选同一种格式的图片", pos=(60, 310), size=(370, 30))
        self.bt_select_photos = wx.Button(
            panel, label='选择图片', pos=(60, 340), size=(370, 30))
        self.bt_select_photos.Bind(wx.EVT_BUTTON, self.SelectPhotos)

        self.bt_start_compress = wx.Button(
            panel, label="开始压缩", pos=(100, 440), size=(120, 40))
        self.bt_start_compress.Bind(wx.EVT_BUTTON, self.StartCompress)
        self.bt_reset = wx.Button(
            panel, label="清空重置", pos=(260, 440), size=(120, 40))
        self.bt_reset.Bind(wx.EVT_BUTTON, self.ResetData)

    def StartCompress(self, event):
        expect_folder = ""
        expect_size = 200
        size = self.text_expect_size.GetValue()
        if size != "" and re.search('[^\d]', size) != None:
            wx.MessageBox("您输入的期望压缩值有误，请修改。")
            return 0
        else:
            expect_size = int(size)

        if self.photo_list == ():
            wx.MessageBox("您还未选择需要压缩的图片！")
            return 0

        if self.text_expect_filePath.GetValue() == "":
            base_path = os.path.dirname(self.photo_list[0])
            expect_folder = base_path + "/CompressedPhotos"
            if not os.path.exists(expect_folder):
                os.mkdir(expect_folder)
        else:
            path = self.text_expect_filePath.GetValue()
            if os.path.isdir(path):
                expect_folder = path
            else:
                wx.MessageBox("您输入的目标文件夹路径有误！\n请重新修正！")
                return 0

        root = tk.Tk()
        root.geometry('500x100')
        progress = ttk.Progressbar(root)
        progress.pack(pady=20)
        progress['length'] = 400
        progress['maximum'] = len(self.photo_list)
        progress['value'] = 0

        method_name = self.method_choose_rbox.GetStringSelection()
        if method_name == "JPG/JPEG":
            for index, item in enumerate(self.photo_list):
                new_photo = expect_folder + "/" + str(index) + ".jpeg"
                self._CompressByPillow(item, new_photo, expect_size)
                progress['value'] += 1
                root.update()
                time.sleep(0.05)
            root.destroy()
            os.startfile(expect_folder)
            self.ResetData(wx.EVT_BUTTON)
        if method_name == "PNG":
            for index, item in enumerate(self.photo_list):
                new_photo = expect_folder + "/" + str(index) + ".png"
                self._CompressByOpenCV(item, new_photo, expect_size)
                progress['value'] += 1
                root.update()
                time.sleep(0.05)
            root.destroy()
            os.startfile(expect_folder)
            self.ResetData(wx.EVT_BUTTON)

    # def _CompressByOpenCV(self, input, output, expect_size):
    #     photo_size = os.path.getsize(input) / 1024
    #     left = 0
    #     right = 9
    #     while True:
    #         mid = int((left+right)/2)
    #         img = cv2.imdecode(np.fromfile(input, dtype=np.uint8), -1)
    #         params = [cv2.IMWRITE_PNG_COMPRESSION, mid]
    #         cv2.imencode('.png', img, params)[1].tofile(output)
    #         photo_size = os.path.getsize(output) / 1024
    #         if right - left <= 1:
    #             break
    #         if photo_size >= expect_size:
    #             left = mid
    #         else:
    #             right = mid

    def _CompressByPillow(self, input, output, expect_size):
        photo_size = os.path.getsize(input) / 1024
        left = 0
        right = 100
        while True:
            mid = int((left+right)/2)
            img = Image.open(input)
            img.save(output, quality=mid)
            photo_size = os.path.getsize(output) / 1024
            if right - left <= 1:
                break
            if photo_size >= expect_size:
                right = mid
            else:
                left = mid

    def ResetData(self, event):
        self.text_expect_size.Clear()
        self.text_expect_filePath.Clear()
        self.method_choose_rbox.SetStringSelection("OpenCV")

    def SelectPhotos(self, event):
        select = tk.Tk()
        select.withdraw()

        # folder_path = filedialog.askdirectory()   # 选择文件夹
        file_path = filedialog.askopenfilenames()   # 选择多个文件

        for index, item in enumerate(file_path):
            if not item.endswith(".jpg") and not item.endswith(".jpeg") and not item.endswith(".png"):
                wx.MessageBox("您选择的图片存在格式错误的情况！\n请重新选择！")
                break
            if index == (len(file_path) - 1):
                self.photo_list = file_path


if __name__ == '__main__':
    app = wx.App()
    frame = CompressFrame(parent=None, id=-1)
    frame.Show()
    app.MainLoop()
